import Konva from 'konva';
import bus from './bus.js';

export default class ImgAnnotate {
  stage = null;
  layer = null;
  // 图片对象
  imageObj = null;
  // 放在konva中的图片对象
  konvaImage = null;
  // 当前绘制的矩形
  currentRect = null;
  // 当前绘制的删除按钮
  currentDelBtn = null;
  // 当前矩形所在的group
  currentGroup = null;
  // 当前选中的group
  selectedGroup = null;
  // 是否正在绘制
  isDrawing = false;
  // 是否点击在group上
  isClickInGroup = false;
  // 是否正在拖拽group
  isDraging = false;
  // konva数据(主要用于记录绘制的矩形数据)
  konvaData = [];
  // 画布上的数据（目前用来进行数据回显）
  annotateData = []
  // canvas的大小
  canvasWidth = 0;
  canvasHeight = 0;

  constructor({ el, canvasSize, imageObj, initData }) {
    this.canvasWidth = canvasSize.width;
    this.canvasHeight = canvasSize.height;
    this.imageObj = imageObj;
    this.stage = new Konva.Stage({
      container: el,
      width: canvasSize.width,
      height: canvasSize.height,
    });

    this.annotateData = initData;
    this.layer = new Konva.Layer();
    this.stage.add(this.layer);
    this.initImage(this.layer);
  }

  // 初始化图片, 添加到layer
  initImage(layer) {
    this.konvaImage = new Konva.Image({
      x: 0,
      y: 0,
      image: this.imageObj,
      width: this.canvasWidth,
      height: this.canvasHeight,
    });
    this.bindEvent();
    // 使用drawHitFromCache需要保证图片和当前执行的代码在同一个域下
    // this.konvaImage.cache();
    // this.konvaImage.drawHitFromCache()
    layer.add(this.konvaImage);
    layer.batchDraw();
    // 绘制已有的矩形
    this.init();
  }

  // 初始化已有的矩形(即数据回显)
  init() {
    if (this.annotateData.length > 0) {
      this.annotateData.forEach((posData) => {
        this.drawContent(null, posData);
      });
      this.layer.batchDraw();
      this.updateCanvasData(); // 初始化完成更新数据
    }
  }

  // 判断当前位置是否在图片上
  getIsPosInImage() {
    const pos = this.stage.getPointerPosition();
    if (pos.x < 0 || pos.x > this.canvasWidth || pos.y < 0 || pos.y > this.canvasHeight) {
      return false;
    }
    return true;
  }

  /*
  * bindEvent 为stage绑定事件
  */
  bindEvent() {
    // 鼠标按下就开始绘制矩形
    this.stage.on('mousedown', (e) => {
      console.log('鼠标按下');
      // 如果点击在group上，则不绘制矩形
      if (this.isClickInGroup) return;
      // 判断鼠标按下所在的位置是否在图片上，如果不在图片上则不绘制
      let isPosInImage = this.getIsPosInImage();
      if (!isPosInImage) return;
      if (!this.isDrawing) {
        this.drawContent(e);
        this.selectedGroup = null;
      }
    });
    // 鼠标移动时更新矩形大小
    this.stage.on('mousemove', (e) => {
      console.log('鼠标移动');
      if (!this.isDrawing) return
      let isPosInImage = this.getIsPosInImage();
      if (!isPosInImage) return;
      this.updateRect(e);
    });
    // 鼠标松开时结束绘制
    this.stage.on('mouseup', (e) => {
      console.log('鼠标松开');
      let isPosInImage = this.getIsPosInImage();
      if (!isPosInImage) return;
      this.endDrawRect(e);
    });
    this.stage.on('mouseleave', (e) => {
      console.log('离开画布');
      this.endDrawRect(e);
    });
  }

  // 新增：安全坐标获取
  getSafePointerPosition() {
    return this.stage.getPointerPosition() || { x: 0, y: 0 };
  }

  // 绘制标注框
  drawContent(e, posData) {
    if (this.isDrawing) return;

    this.isDrawing = true;
    // 创建group组
    this.currentGroup = new Konva.Group({
      draggable: true,
    });

    const pos = posData || this.getSafePointerPosition();
    this.drawRect(pos);

    if (!posData) { // 用户手动绘制，需要获取当前鼠标的位置
    } else {  // 回显数据
      this.drawDelBtn();
      this.isDrawing = false;
    }
    // 为group绑定事件，用于通过鼠标点击group来选中当前的矩形
    this.bindEventForGroup(this.currentGroup);
    this.layer.add(this.currentGroup);
  }

  // 绘制矩形
  drawRect(pos) {
    this.currentRect = new Konva.Rect({
      x: pos.x,
      y: pos.y,
      width: pos.width || 0,
      height: pos.height || 0,
      stroke: '#3387ff',
      fill: '#cee3ff',
      lineJoin: 'round',
      dash: [10, 5],
      strokeWidth: 2,
      opacity: 0.5,
    });
    this.currentGroup.add(this.currentRect);
  }

  // 更新矩形大小
  updateRect(e) {
    if (!this.isDrawing && !this.currentRect) return;
    const pos = this.stage.getPointerPosition();
    const rect = this.currentRect;

    const x = rect.x();
    const y = rect.y();
    rect.width(pos.x - x);
    rect.height(pos.y - y);
    this.layer.batchDraw();
  }

  // 绘制删除按钮
  drawDelBtn() {
    let checkAndRemoveGroup = this.checkAndRemoveGroup.bind(this);
    let radiusSize = 4;
    let width = 0;
    let height = 0;
    let pos = {
      x: this.currentRect.x(),
      y: this.currentRect.y(),
      width: this.currentRect.width(),
      height: this.currentRect.height()
    };
    if (pos.width > 0) {
      width = pos.width;
    }
    if (pos.height < 0) {
      height = pos.height;
    }

    this.currentDeLBtn = new Konva.Circle({
      x: pos.x + width,
      y: pos.y + height,
      radius: radiusSize,
      fill: 'red',
      stroke: 'black',
      strokeWidth: 0
    });

    this.currentDeLBtn.on('mouseover', function (event) {
      event.cancelBubble = true;
      document.body.style.cursor = 'default';
    });
    this.currentDeLBtn.on('click', function (event) {
      event.cancelBubble = true;
      checkAndRemoveGroup(event);
    })
    this.currentGroup.add(this.currentDeLBtn);
  }

  // 结束绘制
  endDrawRect(e) {
    if (!this.isDrawing) return;

    if (this.currentGroup) {
      this.drawDelBtn();
    }
    if (this.currentGroup && this.currentRect) {
      this.normalizeRectPosition();
      // 查询是否有重叠
      if (this.isOverlapping(this.currentRect)) {
        $message.error("禁止重叠");
        this.currentGroup.destroy();
        this.currentRect = null;
        this.currentGroup = null;
        this.layer.batchDraw();

        this.isDrawing = false;
        return;
      }
      // 查询标注框是否过小
      if (this.isRectSize(this.currentRect)) {
        $message.error("请正确标注内容");
        this.currentGroup.destroy();
        this.currentRect = null;
        this.currentGroup = null;
        this.layer.batchDraw();

        this.isDrawing = false;
        return;
      }
    }
    this.isDrawing = false;
    // 将绘制后的数据传送到konvaVueNew中进行保存
    this.updateCanvasData();
    this.getImage(this.currentGroup);
    this.currentRect = null;
    this.currentGroup = null;
  }

  // 自动修正矩形坐标（支持反向绘制）
  normalizeRectPosition() {
    const rect = this.currentRect;
    const newPos = {
      x: rect.x() + (rect.width() < 0 ? rect.width() : 0),
      y: rect.y() + (rect.height() < 0 ? rect.height() : 0),
      width: Math.abs(rect.width()),
      height: Math.abs(rect.height())
    };

    rect.position({ x: newPos.x, y: newPos.y })
    rect.size({ width: newPos.width, height: newPos.height })
  }

  /*
  * bindEventForGroup 为group绑定事件
  */
  bindEventForGroup(group) {
    const layer = this.layer;
    const isOverlapping = this.isOverlapping.bind(this);
    const getImage = this.getImage.bind(this);
    const drawContent = this.drawContent.bind(this);
    const updateCanvasData = this.updateCanvasData.bind(this);
    let groupDragstart = null;

    let that = this;
    // 拖拽边界限制
    group.dragBoundFunc((pos) => {
      let rect = group.findOne("Rect");
      // console.log(pos.y, "边界限制", rect);
      let newX = pos.x
      let newY = pos.y

      let minX = rect.x();
      let maxX = that.canvasWidth - rect.x() - rect.width();
      // 限制X轴边界
      if (newX < -minX) newX = -minX;
      if (newX > maxX) newX = maxX;

      let minY = rect.y();
      let maxY = that.canvasHeight - rect.y() - rect.height();
      // 限制Y轴边界
      if (newY < -minY) newY = -minY;
      if (newY > maxY) newY = maxY;

      return { x: newX, y: newY }
    });

    group.on('mousedown', () => {
      this.isClickInGroup = true;
    });
    group.on('mouseup', () => {
      this.isClickInGroup = false;
    });
    group.on('mouseover', function () {
      document.body.style.cursor = 'pointer';
    });
    group.on('mouseout', function () {
      document.body.style.cursor = 'default';
    });
    group.on('dragstart', function (event) {
      this.isDraging = true;
      document.body.style.cursor = 'pointer';
      // 记录移动前的信息
      let rect = event.target.findOne("Rect");
      groupDragstart = {
        x: rect.x(),
        y: rect.y(),
        width: rect.width(),
        height: rect.height(),
      };
      // console.log("移动前的信息", groupDragstart);
    })
    group.on('dragmove', function (event) {
    })
    group.on('dragend', function (event) {
      let targetRect = event.target.findOne("Rect");
      if (this.isDraging) {
        if (isOverlapping(targetRect)) {
          // 移动完是否重叠
          this.isClickInGroup = false;
          group.destroy();
          drawContent(null, groupDragstart)
          layer.batchDraw();
          // 删除后需要将当前的数据更新
          document.body.style.cursor = 'default';
        } else {
          layer.batchDraw();
        }
        updateCanvasData();
        getImage(group);
      }
      this.isDraging = false;
    })
    group.on('click', function () {
      this.selectedGroup = group;
      // 选中当前group时，将该group的矩形高亮显示, 其他group的矩形恢复原状
      // layer.find('Group').forEach((g) => {
      //   const r = g.findOne('Rect');
      //   r && r.stroke('red');
      // });
      // const rect = group.findOne('Rect');
      // rect.stroke('blue');
      // layer.batchDraw();
    })
  }

  // 更新数据
  updateCanvasData() {
    const data = [];
    this.layer.find('Group').forEach((group) => {
      const rect = group.findOne('Rect');
      if (rect) {
        data.push(group)
      }
    });
    this.konvaData = data;
    bus.emit('canvasData', this.konvaData);
  }

  // 获取当前父级的组元素
  checkAndRemoveGroup(element) {
    // this.layer.find('Group')
    for (let group of this.konvaData) {
      let groupChildren = group.getChildren();
      // console.log(groupChildren, "???checkAndRemoveGroup111", element);
      let isFlag = groupChildren.findIndex(item => item._id == element.target._id);
      if (isFlag != -1) {
        group.destroy(); // 删除整个组
        this.layer.draw(); // 重绘图层以反映更改
        this.updateCanvasData();
      }
    }
  }

  // 检测是否重叠
  isOverlapping(newRect) {
    // console.log(newRect, "isOverlapping -- newRect");
    if (!newRect) return false;
    const newRectBox = newRect.getClientRect();
    // console.log(newRect, "isOverlapping--newRect");

    for (let rect of this.konvaData) {
      const rectBox = rect.getClientRect();
      const oldRect = rect.findOne("Rect");
      // console.log(oldRect, "isOverlapping--rect");
      if (oldRect) {
        if (newRect._id !== oldRect._id) {
          if (Konva.Util.haveIntersection(newRectBox, rectBox)) {
            return true;
          }
        }
      } else {
        if (Konva.Util.haveIntersection(newRectBox, rectBox)) {
          return true;
        }
      }
    }
    return false;
  }

  // 标注框大小
  isRectSize(rect) {
    // console.log('isRectSize', rect);

    if (rect.width() < 30 || rect.height() < 30) {
      return true;
    }
    return false;
  }

  // 根据矩形位置 重新绘制图片并生成file
  getImage(group) {
    // console.log(group, "获取图片信息group");
    let rect = group.findOne("Rect");
    let circle = group.findOne("Circle");
    let dragend = {
      x: group.getAttr("x") || 0,
      y: group.getAttr("y") || 0,
    }
    // console.log("getImage", rect);

    let pos = {
      x: rect.x() + dragend.x,
      y: rect.y() + dragend.y,
      width: rect.width(),
      height: rect.height()
    };

    if (this.isDraging) { // 拖拽完更新
      circle.position({ x: circle.x() + dragend.x, y: circle.y() + dragend.y })
      rect.position({ x: pos.x, y: pos.y })
      group.setX(0);
      group.setY(0);
    }
    const canvas = document.createElement('canvas');
    canvas.width = this.canvasWidth;
    canvas.height = this.canvasHeight;
    const context = canvas.getContext('2d')
    context.drawImage(this.imageObj, 0, 0, canvas.width, canvas.height);
    let imageData = context.getImageData(pos.x, pos.y, pos.width, pos.height);
    canvas.width = pos.width;
    canvas.height = pos.height;
    context.putImageData(imageData, 0, 0)
    const dataURL = canvas.toDataURL('image/png');

    let urlList = {
      dataURL: dataURL,
      parentId: group._id,
      id: rect._id,
    }
    // console.log('生成图片', urlList);

    bus.emit('urlList', urlList);
  }
}